package com.shiva.oms.logview.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ch.ethz.ssh2.ChannelCondition;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.SCPClient;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;

/**
 * 
 * SSH连接linux服务器，执行命令或传输文件等操作
 * 
 * <pre>
 * HISTORY
 * ****************************************************************************
 *  ID    DATE            PERSON            REASON
 *  1     2018年4月13日         LA.01367604           Create
 * ****************************************************************************
 * </pre>
 * 
 * @author LA.01367604
 * @version 1.0
 */
public class SshTransferHelper {
    
    private static final Logger logger = LoggerFactory.getLogger(SshTransferHelper.class);
    
    private String IP = "10.202.38.213";
    private String USERNAME = "appdeploy";
    private String PASSWORD = "sf123456";
    private Connection conn = null;
    //private String PATH = "/app/jetty/server/SHIVA_OMS_CNSZ22_JETTY_APP_REC_ORDER_01/logs/";// /home/appdeploy/appointment/logs/ /app/jetty/server/SHIVA_OMS_CNSZ22_JETTY_APP_REC_ORDER_01/logs
    private final static String COMMOND_GET_FILES_BY_DIR = "ls -l %s | grep ^-";// 排除掉子目录
    private final static String COMMOND_GET_FILE_CONCENT = "cat %s";// 获取指定文件内容
    private final static String LINUX_FILE_SEP = "/";

    
    public SshTransferHelper() {}
    public SshTransferHelper(String ip, String user, String password) {
        this.IP = ip;
        this.USERNAME = user;
        this.PASSWORD = password;
        connectHost(ip, user, password);
    }

    /**
     * 连接目标服务器并认证用户
     * 
     * @param ip
     * @param user
     * @param password
     * @return Connection
     * @author LA.01367604-2018年4月13日
     */
    public boolean connectHost(String ip, String user, String password) {
        try {
            this.conn = new Connection(ip);
            this.conn.connect();
            boolean isAuthenticated = this.conn.authenticateWithPassword(user, password);
            logger.info("Connecting to "+ ip + "@" + user + (isAuthenticated?" successful":" failed"));
            if (!isAuthenticated) {
                this.conn = null;
                return false;
            }
            return true;
        } catch (IOException e) {
            logger.error("connect to host error :", e);
            this.conn = null;
            return false;
        }
    }

    public List<String> getFileNamesFromDir(String fileDir) {
        List<String> fileNames = new ArrayList<>();
        if (!isConnected()) {
            return fileNames;
        }
        Session session = null;
        try {
            session = this.conn.openSession();
            String command = String.format(COMMOND_GET_FILES_BY_DIR, fileDir);
            session.execCommand(command);// 远程执行命令
            InputStream is = new StreamGobbler(session.getStdout());
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            while (true) {
                String line = br.readLine();
                if (line == null) {
                    break;
                }
                String name = line.substring(line.lastIndexOf(" ") + 1, line.length());
                // System.out.println(name);
                fileNames.add(name);
            }
        } catch (IOException e) {
            logger.error("exec command error!", e);
            fileNames = null;
        } finally {
            if (session != null) {
                session.close();
            }
        }
        return fileNames;
    }

    /**
     * 从远程服务器上复制文件到本地
     * 
     * @param conn
     * @param filePath
     * @param destPath
     * @author LA.01367604-2018年4月13日
     */
    public void copyFile(String filePath, String destPath) {
        if (!isConnected()) {
            return;
        }
        try {
            SCPClient scpClient = conn.createSCPClient();
            // OutputStream os = new FileOutputStream(new File(destPath));
            scpClient.get(filePath, destPath);// scp 复制文件到本地
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 从远程服务器上读取文件内容到IO流
     * 
     * @param fileDir
     * @param fileName
     * @return
     * @author LA.01367604-2018年4月13日
     */
    public InputStream getFileContent(String fileDir, String fileName) {
        InputStream is = null;
        if (isConnected()) {
            Session session = null;
            try {
                session = conn.openSession();
                String command = String.format(COMMOND_GET_FILE_CONCENT, buildPath(fileDir, fileName));
                session.execCommand(command);// 远程执行命令
                is = new StreamGobbler(session.getStdout());
                // 等待，除非1.连接关闭；2.输出数据传送完毕；3.进程状态为退出；4.超时
                session.waitForCondition(ChannelCondition.CLOSED | ChannelCondition.EOF | ChannelCondition.EXIT_STATUS , 60000);  
            } catch (IOException e) {
                logger.error("exec command error!", e);
            } finally {
                if (session != null) {
                    session.close();
                }
            }
        }
        return is;
    }

    private String buildPath(String fileDir, String fileName) {
        return (fileDir.endsWith(LINUX_FILE_SEP)) ? fileDir + fileName : fileDir + LINUX_FILE_SEP + fileName;
    }

    public void closeConnect() {
        if (this.conn != null) {
            conn.close();
        }
    }

    public boolean isConnected() {
        return (null != this.conn);
    }

    public void reConnect() {
        connectHost(this.IP, this.USERNAME, this.PASSWORD);
    }

    /**
     * 打印读取的信息流（测试）
     * 
     * @param is
     * @author LA.01367604-2018年4月23日
     */
    public static void readByLine(InputStream is) {
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        while (true) {
            try {
                String line = br.readLine();
                if (line == null) {
                    System.out.println("远程服务器返回信息:空");
                    break;
                }
                System.out.println(line);
            } catch (IOException e) {
                // TODO 自动生成的 catch 块
                e.printStackTrace();
            }
        }
    }
    
}
